package it.netsphere.nswing.comp;

import it.netsphere.nswing.event.NSEventManager;
import it.netsphere.nswing.util.ComboItem;
import it.redstar.annotated.swing.IComboIdentifier;

import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;

import javax.swing.JComboBox;

import ognl.Ognl;

@SuppressWarnings("rawtypes")
public class NSComboBox extends JComboBox {

    public static org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(NSComboBox.class);

    private static final long serialVersionUID = -2629119064695178994L;

    public NSComboBox() {
        super.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() != ItemEvent.SELECTED)
                    return;

                if (getUserObject() != null && getUserObjectField() != null && updatingData == false) {
                    try {
                        if (isTitleItem && getSelectedIndex() == 0) {
                            Ognl.setValue(getUserObjectField(), getUserObject(), null);
                        } else {
                            Object v = Ognl.getValue(getUserObjectField(), getUserObject());
                            if (v != getSelectedItem())
                                Ognl.setValue(getUserObjectField(), getUserObject(), getSelectedItem());
                        }
                    } catch (Exception ee) {
                        throw new RuntimeException(ee);
                    }
                }

                // LOG.debug( e );
                notifySelection();
            }
        });
    }

    private String regexp;

    public String getRegExp() {
        return regexp;
    }

    public void setRegExp(String regexp) {
        this.regexp = regexp;
        updateRenderer();
    }

    private String selectionEventCode;

    public String getSelectionEventCode() {
        return selectionEventCode;
    }

    public void setSelectionEventCode(String selectionEventCode) {
        this.selectionEventCode = selectionEventCode;
    }

    @SuppressWarnings("unchecked")
    private void updateRenderer() {
        if (getRegExp() == null)
            return;

        setRenderer(new NSComboBoxRenderer(getRegExp()));

    }

    public void setSelectedId(int id) {
        setSelectedIndex(-1);

        for (int c = 0; c < getItemCount(); c++) {
            if (getItemAt(c) instanceof ComboItem) {
                ComboItem item = (ComboItem) getItemAt(c);
                if (item != null && item.getComboId() == id) {
                    setSelectedIndex(c);
                    return;
                }
            }
        }

        if (isTitleItem) {
            setSelectedIndex(0);
        }

    }

    private boolean updatingData;

    private boolean isTitleItem = false;

    @SuppressWarnings({ "unchecked" })
    public void setData(List<?> l, Object firstEntry) {
        try {
            updatingData = true;

            removeAllItems();

            if (firstEntry != null) {
                addItem(firstEntry);
                isTitleItem = true;
            }

            for (Object o : l) {
                addItem(o);
            }

            updateSelectedItem();

        } finally {

            updatingData = false;
        }

    }

    private void updateSelectedItem() {
        if (getUserObject() != null && getUserObjectField() != null) {
            try {
                IComboIdentifier v = (IComboIdentifier) Ognl.getValue(getUserObjectField(), getUserObject());
                if (v == null) {
                    setSelectedId(-1);
                    return;
                }

                for (int c = 0; c < getItemCount(); c++) {
                    IComboIdentifier item = (IComboIdentifier) getItemAt(c);
                    if (v.getComboId() == item.getComboId()) {
                        setSelectedItem(item);
                        break;
                    }
                }
            } catch (Exception e) {
                LOG.error(e.getMessage());
                throw new RuntimeException(e);
            }
        }

    }

    private void notifySelection() {
        if (getSelectionEventCode() != null)
            NSEventManager.dispatchUIEvent(getSelectionEventCode(), getSelectedItem());
    }

    private Object userObject;

    public Object getUserObject() {
        return userObject;
    }

    public void setUserObject(Object userObject) {
        this.userObject = userObject;
        updateSelectedItem();
    }

    private String userObjectField;

    public String getUserObjectField() {
        return userObjectField;
    }

    public void setUserObjectField(String userObjectField) {
        this.userObjectField = userObjectField;
        updateSelectedItem();
    }

    public void setMapping(Object o, String field) {
        setUserObject(o);
        setUserObjectField(field);
    }

    public ComboItem getComboItemById(int id) {
        for (int c = 0; c < getItemCount(); c++) {
            ComboItem ci = (ComboItem) getItemAt(c);
            if (ci.getComboId() == id)
                return ci;
        }

        return null;
    }
}
